package com.hsmpay.yl8583.service;

import com.hsmpay.mobile.util.jiamiji.HsmEngine;
import com.hsmpay.utils.DesUtil;
import com.hsmpay.utils.WriteFile;
import com.hsmpay.utils.system.ConConfig;
import com.hsmpay.yl8583.utils.*;
import com.iso8583.Iso8583Composer;
import com.iso8583.Iso8583Parser;
import com.iso8583.util.ByteUtils;
import com.iso8583.util.J8583Util;
import com.iso8583.util.PosUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by zhy on 15/10/22.
 */
public class YinShengBaoSocketToBoss {
    private ApplicationContext act;
    static WriteFile wf = new WriteFile("ds_YinShengBao");
    public static String debug = ConConfig.getAttribute("YINSHENGBAO_DAISHOU_DEBUG_STATUS");
    private static final Logger log = Logger.getLogger(YinShengBaoSocketToBoss.class);

    //银联生产平台
    static String ipAdd="180.166.114.158";
    static String IPort="5555";
    String itimeout="60000";
    String ShopCode = "800310000015821";//商户号
    String PosNo = "50000090";			//终端号
    String organizationId = "20151023";         //机构号
    String orgId = "321310001720";
    String tpdu = "6000060001";
//    String header = "603100310001";
    String batch = "000001"; 			 // 批次号
    String serialNumber = "100013"; 	 // 系统跟踪号(POS中心流水号)
    String operator="001";				 //操作员
    String bit62 = "";
    //密文报文密钥
    String MacKey="CD3BEC830CAD5EA767174CC42C3C930E";
    //密文密码密钥
    String PinKey="F033F39A20309A2DC6968C1A07E6120E";
    //密文磁道密钥
    String trkKey="AE50A271FB4811631E62FD28E19CA04E";

    //主密钥
    String MasterKey="22222222222222222222222222222222";

    Integer MASTERKEY_INDEX = null;
    String HsmEngine_Ip = "";
    Integer HsmEngine_port = null;

    /**
     * 通信检测(0000)
     *
     * @return 是否正常
     */
    public String detection(byte[] sendStr) {
        SendSocket send = new SendSocket(ipAdd, IPort, itimeout,wf);
        return send.detection(sendStr);
    }

    /**
     * 构造方法
     * @param ShopCode
     * @param PosNo
     * @param batch
     * @param MasterKey
     * @param PinKey
     * @param MacKey
     * @param trkKey
     */
    public YinShengBaoSocketToBoss(String ShopCode, String PosNo, String batch, String MasterKey, String PinKey, String MacKey, String trkKey, Map<String,String> settings) {

        if (null != settings){
            this.ipAdd = settings.containsKey("ysbIp") ? settings.get("ysbIp") : "";
            this.IPort = settings.containsKey("ysbPort") ? settings.get("ysbPort") : "";
            this.MASTERKEY_INDEX = settings.containsKey("index") ? Integer.valueOf(settings.get("index")) : null;
            this.HsmEngine_Ip = settings.containsKey("hsmEngineIp") ? settings.get("hsmEngineIp") : "";
            this.HsmEngine_port = settings.containsKey("hsmEnginePort") ? Integer.valueOf(settings.get("hsmEnginePort")) : null;
        }

        this.ShopCode = ShopCode;
        this.PosNo = PosNo;
        this.batch = batch;
        this.MasterKey = MasterKey;
        this.PinKey = PinKey;
        this.MacKey = MacKey;
        this.trkKey = trkKey;
        if(StringUtils.isEmpty(batch.trim())){
            this.batch = "000001";
        }
        act = SpringUtil.getApplicationContext();//new ClassPathXmlApplicationContext("anxinybConfig.xml");

        wf.log("tpdu:" + this.tpdu, "调试");
        wf.log("ShopCode(商户号):" + this.ShopCode, "调试");
        wf.log("PosNo(终端号):" + this.PosNo, "调试");
        wf.log("batch(批次号):" + this.batch, "调试");
        wf.log("ZMKKey:" + this.MasterKey, "调试");
        wf.log("PinKey:" + this.PinKey, "调试");
        wf.log("MacKey:" + this.MacKey, "调试");
        wf.log("trkKey:" + this.trkKey, "调试");
    }

    /**
     * 签到
     * @param bankOrderNum
     * @return
     */
    public String Login0800(String bankOrderNum) throws Exception {
        String LoginMsg = "";
        String TYPE_ID = "0800";
        String mustFields = "";
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);//tpdu
        body.put("HEAD","");//HEAD
        body.put("PRO_COD", "900000");//第三域
        body.put("ACQ_COD", this.organizationId);//32域
        body.put("F33", this.organizationId);//33域
        body.put("RESE_PRI_60", "310");//60域
        String optionalFields = "3|32|33|60";
        //生成报文
        System.out.println("银生宝签到生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optionalFields, TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage, false);//此处false代表加不加空格
        wf.log("银生宝签到请求报文为：" + req, "调试");
        System.out.println("银生宝签到请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAdd, Integer.valueOf(this.IPort));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("银生宝签到响应报文是：" + res);
        wf.log("银生宝签到响应报文为：" + res, "调试");
        PosUtil.analysis8583(res);
        try {
            //解析报文
            byte[] bytes = ByteUtils.hexStringToByte(res);
            Map<String, String> map = Iso8583Parser.parser("POS", bytes, true);
            //处理解析的map
            //分别获取39,60,62域
            String bit39 = map.get("39");
            String bit60 = map.get("60");
            String bit48 = map.get("48");
            System.out.println("bit48----->" +bit48);
            if (StringUtils.isBlank(bit48) || (StringUtils.isNotBlank(bit48) && bit48.length()!= 96)){
                wf.log("银生宝签到返回报文格式错误","调试");
                return "-1_";
            }

            String PIK = bit48.substring(0,32);
            String MAK = bit48.substring(32, 64);
            String TDK = bit48.substring(64, 96);

            //使用加密机转加密工作密钥
            HsmEngine hsmEngine = new HsmEngine(HsmEngine_Ip,HsmEngine_port);
            String LPK = hsmEngine.transZPK(MASTERKEY_INDEX,PIK);//pinKey
            String LAK = hsmEngine.transZAK(MASTERKEY_INDEX,MAK);//macKey
            String LEK = hsmEngine.transZEK(MASTERKEY_INDEX,TDK);//trackKey

//            LoginMsg = "0_"+ bit39+ "_" + this.batch + "_" + PIK + "_" + MAK + "_" + TDK;
            LoginMsg = "0_"+ bit39+ "_" + this.batch + "_" + LPK + "_" + LAK + "_" + LEK;
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("银生宝签到返回报文解析报文错误");
            wf.log("银生宝签到返回报文解析错误" ,"调试");
        }
        return LoginMsg;
    }

    /**
     * 查询余额
     * @param trk2
     * @param trk3
     * @param pin
     * @param accountNumber
     * @param bankOrderNum
     * @param bit23
     * @param bit55
     * @param bit14
     * @return
     */
    public String Query(String trk2, String trk3, String pin, String accountNumber, String bankOrderNum, String bit23, String bit55, String bit14) throws Exception {
//        String MasterKey = this.MasterKey;
//        String PIK = this.PinKey;
//        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
//        String TDK = DesUtil.decode3DES(this.trkKey, MasterKey);
//        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, MasterKey);

        //通过加密机去计算PINBlock
        HsmEngine hsmEngine = new HsmEngine(HsmEngine_Ip,HsmEngine_port);
        String des_pin = hsmEngine.encryptPin(pin,accountNumber,this.PinKey);
        String QueryMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "310000");
        optionalFields.append("3|");
        body.put("CSEQ_NO", bankOrderNum);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("ACQ_COD", this.organizationId);
        optionalFields.append("32|");
        body.put("F33", this.organizationId);
        optionalFields.append("33|");
        if (!"".equals(trk2.trim())) {
//            trk2 = DesUtil.ySBEncryptStanderTranck(TDK, trk2);
            int trk2Len=trk2.length();
            trk2 = trk2Len + trk2;
            int newTrk2Len = trk2.length();
            int mod=newTrk2Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk2+="0";
            }
            trk2 = hsmEngine.encryptTrackD3(trk2,this.trkKey);
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
//            trk3 = DesUtil.ySBEncryptStanderTranck(TDK, trk3);
            int trk3Len=trk3.length();
            trk3 = trk3Len + trk3;
            int newTrk3Len = trk3.length();
            int mod = newTrk3Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk3+="0";
            }
            trk3 = hsmEngine.encryptTrackD3(trk3,this.trkKey);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        body.put("RESE_PRI_60", "310");
        optionalFields.append("60|");
        //62域
        body.put("RESE_PRI_62", bankOrderNum + this.batch);
        optionalFields.append("62");
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(10,request.length()-16);
//        String macstr = TestDes.MakeANSI919Mac(MAK, sub, null);//加密操作,传参问题
        String macstr = hsmEngine.encryptMacMS(sub,this.MacKey);
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("银生宝查询余额生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        //PosUtil.analysis8583(req);//解析请求报文
        wf.log("银生宝查询余额请求报文为：" + req, "调试");
        System.out.println("银生宝查询余额请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, this.ipAdd, Integer.valueOf(this.IPort));
        String res = ByteUtils.byte2HexStr(response, false);
        if ((!"-1".equals(res)) && (!"".equals(res))) {
            System.out.println("银生宝查询余额响应报文是：" + res);
            wf.log("银生宝查询余额响应报文为：" + res, "调试");
            try {
                PosUtil.analysis8583(res);
                //解析报文
                Map<String, String> map = Iso8583Parser.parser("POS", response, true);
                //第4域为现金账户可用余额
                String result39 = map.get("39");
                if ("00".equals(result39)){
                    String result4 = map.get("4");
                    QueryMsg = "0" + "_" + result39 + "_" + result4;
                }else {
                    QueryMsg = "0" + "_" + result39;
                }
                //获取域值信息，处理返回数据
            }catch (Exception e) {
                e.printStackTrace();
                System.out.println("银生宝查询余额解析错误");
                wf.log("银生宝查询余额解析错误", "调试");
            }
        }else {
            QueryMsg = "-1_";
        }
        wf.log("银生宝佘额查询返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }
    /**
     * 消费
     * @param trk2
     * @param trk3
     * @param pin
     * @param money
     * @param accountNumber
     * @param bankOrderNum
     * @param bit23
     * @param bit55
     * @param bit14
     * @return
     */
    public String BillPayment(String trk2, String trk3, String pin, String money, String accountNumber, String bankOrderNum, String bit23, String bit55, String bit14) throws Exception {
//        String MasterKey = this.MasterKey;
//        String PIK = this.PinKey;
//        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
//        String TDK = DesUtil.decode3DES(this.trkKey, MasterKey);
//        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, MasterKey);
        //通过加密机去计算PINBlock
        HsmEngine hsmEngine = new HsmEngine(HsmEngine_Ip,HsmEngine_port);
        String des_pin = hsmEngine.encryptPin(pin,accountNumber,this.PinKey);
        String comsumeMsg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        //body.put("HEAD", this.header);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "000000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", bankOrderNum);
        System.out.println("银生宝终端交易流水号：" + bankOrderNum);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("ACQ_COD", this.organizationId);
        optionalFields.append("32|");
        body.put("F33", this.organizationId);
        optionalFields.append("33|");
        if (!"".equals(trk2.trim())) {
            System.out.println("trk2....." + trk2);
//            trk2 = DesUtil.ySBEncryptStanderTranck(TDK, trk2);

            int trk2Len=trk2.length();
            trk2 = trk2Len + trk2;
            int newTrk2Len = trk2.length();
            int mod=newTrk2Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk2+="0";
            }
            trk2 = hsmEngine.encryptTrackD3(trk2,this.trkKey);

            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
//            trk3 = DesUtil.ySBEncryptStanderTranck(TDK, trk3);
            int trk3Len=trk3.length();
            trk3 = trk3Len + trk3;
            int newTrk3Len = trk3.length();
            int mod = newTrk3Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk3+="0";
            }
            trk3 = hsmEngine.encryptTrackD3(trk3,this.trkKey);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2600000000000000");
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        body.put("RESE_PRI_60", "310");
        optionalFields.append("60|");
        //62域
        String bit62 = bankOrderNum + this.batch;
        body.put("RESE_PRI_62", bit62);
        optionalFields.append("62");
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(10, request.length()-16);
        //63域是否要出现
//        String macstr = TestDes.MakeANSI919Mac(MAK, sub, null);//加密操作,传参问题
        String macstr = hsmEngine.encryptMacMS(sub,this.MacKey);
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("银生宝消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.analysis8583(req.substring(4));//解析请求报文
        wf.log("银生宝消费请求报文为：" + req, "调试");
        System.out.println("银生宝消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAdd, Integer.valueOf(IPort));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("银生宝消费响应报文是：" + res);
        wf.log("银生宝消费响应报文为：" + res, "调试");
        try {
            if ((!"-1".equals(res)) && (!"".equals(res))){
            PosUtil.analysis8583(res);
            //解析报文,返回解析的域map
            Map<String, String> map = Iso8583Parser.parser("pos", response, true);
            //需要获取2,4,11,12,13,14,37,38,39域信息
            String result2 = map.get("2");
            String result4 = map.get("4");
            String result11 = map.get("11");
            String result12 = map.get("12");
            String result13 = map.get("13");
            String result14 = map.get("14");
            String result37 = map.get("37");
            String result38 = map.get("38");
            String result39 = map.get("39");
            comsumeMsg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +result13 + "_" + result14 + "_" +result37 + "_" + result38 +"_"+result39;
            }else{
                comsumeMsg = "-1_";
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("银生宝消费响应报文解析错误");
            wf.log("银生宝消费响应报文解析错误", "调试");
        }
        wf.log("银生宝消费返回数据:" + comsumeMsg, "调试");
        return comsumeMsg;
    }

    /**
     * 冲正
     * @param trk2
     * @param trk3
     * @param money
     * @param accountNumber
     * @param serialNumber
     * @param bit39
     * @param bit38
     * @param bit23
     * @param bit55
     * @param bit14
     * @param bit61
     * @return
     * @throws Exception
     */
    public String unBillPayment(String trk2, String trk3,String money,String accountNumber,String bankOrderNum, String serialNumber,String bit39,String bit38,String bit23,String bit55,String bit14,String bit61) throws Exception {
//        String MasterKey = this.MasterKey;
//        String MAK = DesUtil.decode3DES(this.MacKey, MasterKey);
        String QueryMsg = "";
        String typeCode = "0420";//消息类型
        String mustFields = "";
        StringBuffer optinalFields = new StringBuffer("");
        HashMap<String, String> body = new HashMap<String, String>();
        body.put("TPDU", this.tpdu);
        //body.put("HEAD",this.header);
        body.put("PAN", accountNumber);//主账号 2
        optinalFields.append("2|");
        body.put("PRO_COD", "000000");//交易处理码 3 跟原交易相同
        optinalFields.append("3|");
        body.put("TTXN_AMT", money);//交易金额 4  跟原交易相同
        optinalFields.append("4|");
        body.put("CSEQ_NO", serialNumber); //受卡方系统跟踪号 同原交易
        optinalFields.append("11|");
        if (!"".equals(bit14)){
            body.put("EXP_DT", bit14);//14
            optinalFields.append("14|");
        }
        body.put("ACQ_COD", this.organizationId);
        optinalFields.append("32|");
        body.put("F33", this.organizationId);
        optinalFields.append("33|");
        //38域需要判断应答码中是否存在
//        if (StringUtils.isNotBlank(bit38)){
//            body.put("AUT_CD", bit38);//授权标识应答码 38 如果原始交易的应答中有授权码，则须填入原交易授权码 从响应报文中获取
//            optinalFields.append("38|");
//        }
        body.put("TRM_NO", this.PosNo);//受卡机终端标识码 41 同原消费交易
        optinalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);//受卡方标识码 42
        optinalFields.append("42|");
        body.put("CCY", "156");//交易货币代码 49
        optinalFields.append("49|");
        if (!"".equals(bit55)){
            body.put("IC_DAT",bit55);//交易货币代码 49
            optinalFields.append("55|");
        }
        body.put("RESE_PRI_60", "310");
        optinalFields.append("60|");
        body.put("RESE_PRI_62", bankOrderNum + this.batch);
        optinalFields.append("62");
        optinalFields.append("|64");
        body.put("F64", "");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.composeYinSheng(mustFields, optinalFields.toString(), typeCode, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(10, request.length()-16);
//        String macstr = TestDes.MakeANSI919Mac(MAK, sub, null);//加密操作,传参问题
        HsmEngine hsmEngine = new HsmEngine(HsmEngine_Ip,HsmEngine_port);
        String macstr = hsmEngine.encryptMacMS(sub,this.MacKey);
        body.put("F64", macstr);
        System.out.println("optionalFields " + optinalFields.toString());
        //生成报文
        System.out.println("银生宝消费冲正生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optinalFields.toString(), typeCode, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        wf.log("银生宝消费冲正请求报文为：" + req, "调试");
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAdd, Integer.valueOf(IPort));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("银生宝消费冲正响应报文是：" + res);
        wf.log("银生宝消费冲正响应报文为：" + res, "调试");
        try {
            if ((!"-1".equals(res)) && (!"".equals(res))){
                PosUtil.analysis8583(res);
                //解析报文
                byte[] bytes = ByteUtils.hexStringToByte(res);
                Map<String, String> map = Iso8583Parser.parser("POS", bytes, true);
                //处理2,4,11,12,13,14,37,38,39,44,61域信息
                String temp2 = map.get("2");
                String temp4 = map.get("4");
                String temp11 = map.get("11");
                String temp12 = map.get("12");
                String temp13 = map.get("13");
                String temp14 = map.get("14");
                String temp37 = map.get("37");
                String temp38 = map.get("38");
                String temp39 = map.get("39");
                String temp44 = map.get("44");
                String temp62 = map.get("62");
                QueryMsg = "0_" + temp2+"_"+temp4+"_"+temp11+"_"+temp12+"_"+temp13+"_"+temp14+"_"+temp37+"_"+temp38+"_"+temp39+"_"+temp44+"_"+temp62;
            }else{
                QueryMsg = "-1_";
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("银生宝消费冲正响应报文解析错误");
            wf.log("银生宝消费冲正响应报文解析错误", "调试");
        }
        wf.log("银生宝消费冲正返回数据:" + QueryMsg, "调试");
        return QueryMsg;
    }

    /**
     * 撤销交易
     * @param trk2
     * @param trk3
     * @param pin
     * @param money
     * @param accountNumber
     * @param bankOrderNum
     * @param bankRef
     * @param authorizationCode
     * @param orgMerchantOrderId
     * @param bit23
     * @param bit55
     * @param bit14
     * @return
     */
    public String undoBillPayment(String trk2, String trk3, String pin, String money, String accountNumber, String bankOrderNum, String bankRef, String authorizationCode, String orgMerchantOrderId, String bit23, String bit55, String bit14,String serialNumber) throws Exception {
//        String masterKey = this.MasterKey;
//        String PIK = this.PinKey;
//        String MAK = DesUtil.decode3DES(this.MacKey, masterKey);
//        String TRK = DesUtil.decode3DES(this.trkKey, masterKey);
//        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, this.MasterKey);

        //通过加密机去计算PINBlock
        HsmEngine hsmEngine = new HsmEngine(HsmEngine_Ip,HsmEngine_port);
        String des_pin = hsmEngine.encryptPin(pin,accountNumber,this.PinKey);
        String msg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();
        wf.log("-------------------请求包域值信息-------------------", "调试");
        body.put("TPDU", this.tpdu);
        //body.put("HEAD", this.header);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "200000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNumber);
        optionalFields.append("11|");
        if (!"".equals(bit14.trim())) {
            body.put("EXP_DT", bit14);
            optionalFields.append("14|");
        }
        if ("".equals(bit55.trim())) {
            body.put("IN_MOD", "021");
            optionalFields.append("22|");
        }else {
            body.put("IN_MOD", "051");
            optionalFields.append("22|");
        }
        if (!"".equals(bit23.trim())) {
            body.put("SEP_NUM", bit23);
            optionalFields.append("23|");
        }
        body.put("ACQ_COD", this.organizationId);
        optionalFields.append("32|");
        body.put("F33", this.organizationId);
        optionalFields.append("33|");
        if (!"".equals(trk2.trim())) {
//            trk2 = DesUtil.ySBEncryptStanderTranck(TRK, trk2);
            int trk2Len=trk2.length();
            trk2 = trk2Len + trk2;
            int newTrk2Len = trk2.length();
            int mod=newTrk2Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk2+="0";
            }
            trk2 = hsmEngine.encryptTrackD3(trk2,this.trkKey);
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        if (!"".equals(trk3.trim())) {
//            trk3 = DesUtil.ySBEncryptStanderTranck(TRK, trk3);
            int trk3Len=trk3.length();
            trk3 = trk3Len + trk3;
            int newTrk3Len = trk3.length();
            int mod = newTrk3Len%16;
            log.debug("mod:"+mod);
            for(int i=0;i<16-mod;i++){
                trk3+="0";
            }
            trk3 = hsmEngine.encryptTrackD3(trk3,this.trkKey);
            body.put("TRACK_3", trk3);
            optionalFields.append("36|");
        }
        body.put("RET_RE_NO", bankRef);
        optionalFields.append("37|");
        body.put("TRM_NO", this.PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", this.ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2600000000000000");
        optionalFields.append("53|");
        if (!"".equals(bit55.trim())) {
            body.put("IC_DAT", bit55);
            optionalFields.append("55|");
        }
        body.put("RESE_PRI_60", "310");
        optionalFields.append("60|");
        //62域
        String bit62 = bankOrderNum + this.batch;
        body.put("RESE_PRI_62", bit62);
        optionalFields.append("62");
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(10, request.length()-16);
        //63域是否要出现
//        String macstr = TestDes.MakeANSI919Mac(MAK, sub, null);//加密操作,传参问题
        String macstr = hsmEngine.encryptMacMS(sub,this.MacKey);
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("银生宝消费生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.analysis8583(req.substring(4));//解析请求报文
        wf.log("银生宝消费请求报文为：" + req, "调试");
        System.out.println("银生宝消费请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ipAdd, Integer.valueOf(IPort));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("银生宝消费响应报文是：" + res);
        wf.log("银生宝消费响应报文为：" + res, "调试");
        try {
            if ((!"-1".equals(res)) && (!"".equals(res))){
                PosUtil.analysis8583(res);
                //解析报文,返回解析的域map
                Map<String, String> map = Iso8583Parser.parser("pos", response, true);
                //需要获取2,4,11,12,13,14,37,38,39域信息
                String result2 = map.get("2");
                String result4 = map.get("4");
                String result11 = map.get("11");
                String result12 = map.get("12");
                String result13 = map.get("13");
                String result14 = map.get("14");
                String result37 = map.get("37");
                String result38 = map.get("38");
                String result39 = map.get("39");
                String result44 = map.get("61");
                String result62 = map.get("62");
                msg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +
                        result13 + "_" + result14 + "_" +result37 + "_" + result38 +"_"+result39 +
                        "_" +result44 + "_" + result62;
            }else{
                msg = "-1_";
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("银生宝消费响应报文解析错误");
            wf.log("银生宝消费响应报文解析错误", "调试");
        }
        wf.log("银生宝消费返回数据:" + msg, "调试");
        return msg;
    }
    public static void main(String[] argus) throws Exception {
        String masterKey = "22222222222222222222222222222222";
        String PIK = "0BB54124477FDDE0C77296F4B79531E3";
        String MAK = DesUtil.decode3DES("158D2124AA2BC8374EDCE16B3F2F689E", masterKey);
        String TRK = DesUtil.decode3DES("C1D12E2CFFE60E93F5A3DAFC7F50B73D", masterKey);
        String accountNumber = "6228480018375384676";
        String pin = "800114";
        String des_pin = TestDes.MakeDesPin(accountNumber, pin, PIK, masterKey);
        String msg = "";
        String TYPE_ID = "0200";
        String mustFields = "";
        String organizationId = "20151023";
        String trk2 = "6228480018375384676d24092200216390000";
        String bankRef = "291000373228";
        String PosNo = "50000090";
        String ShopCode = "800310000015821";
        String batch = "000001";
        String ip = "180.166.114.158";
        String port = "5555";
        String money = "000000002000";
        String bankOrderNum = "100256";
        String serialNum = "100260";
        String tpdu = "6000060001";
        StringBuffer optionalFields = new StringBuffer("");
        HashMap<String,String> body = new HashMap<String,String>();

        body.put("TPDU", tpdu);
        body.put("PAN", accountNumber);
        optionalFields.append("2|");
        body.put("PRO_COD", "200000");
        optionalFields.append("3|");
        body.put("TTXN_AMT", money);
        optionalFields.append("4|");
        body.put("CSEQ_NO", serialNum);
        optionalFields.append("11|");
        body.put("IN_MOD", "021");
        optionalFields.append("22|");
        body.put("ACQ_COD", organizationId);
        optionalFields.append("32|");
        body.put("F33", organizationId);
        optionalFields.append("33|");
        if (!"".equals(trk2.trim())) {
            trk2 = DesUtil.ySBEncryptStanderTranck(TRK, trk2);
            body.put("TRACK_2", trk2);
            optionalFields.append("35|");
        }
        body.put("RET_RE_NO", bankRef);
        optionalFields.append("37|");
        body.put("TRM_NO", PosNo);
        optionalFields.append("41|");
        body.put("MERC_CD", ShopCode);
        optionalFields.append("42|");
        body.put("CCY", "156");
        optionalFields.append("49|");
        body.put("PIN_DATA", des_pin);
        optionalFields.append("52|");
        body.put("SECUR_INF", "2600000000000000");
        optionalFields.append("53|");
        body.put("RESE_PRI_60", "310");
        optionalFields.append("60|");
        //62域
        String bit62 = bankOrderNum + batch;
        body.put("RESE_PRI_62", bit62);
        optionalFields.append("62");
        optionalFields.append("|64");
        body.put("F64","");
        Iso8583Composer com = new Iso8583Composer();
        byte[] MacMessage = com.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        String request = ByteUtils.byte2HexStr(MacMessage,false);
        String sub = request.substring(10, request.length()-16);
        //63域是否要出现
        String macstr = TestDes.MakeANSI919Mac(MAK, sub, null);//加密操作,传参问题
        body.put("F64", macstr);
        System.out.println("optionalFields " + optionalFields.toString());
        //生成报文
        System.out.println("银生宝撤销生成请求报文...");
        Iso8583Composer composer = new Iso8583Composer();
        byte[] unMacMessage = composer.composeYinSheng(mustFields, optionalFields.toString(), TYPE_ID, body, "pos", true);
        unMacMessage = J8583Util.getLength(unMacMessage);
        for (int i=0; i<unMacMessage.length; i++) {
            System.out.print(unMacMessage[i] + ",");
        }
        System.out.println();
        String req = ByteUtils.byte2HexStr(unMacMessage,false);//此处false代表加不加空格
        PosUtil.analysis8583(req.substring(4));//解析请求报文

        System.out.println("银生宝撤销请求报文为：" + req);
        //发送请求报文，并且返回响应
        byte[] response = PosUtil.sendPosMsg(unMacMessage, ip, Integer.valueOf(port));
        String res = ByteUtils.byte2HexStr(response, false);
        System.out.println("银生宝撤销响应报文是：" + res);

        try {
            if ((!"-1".equals(res)) && (!"".equals(res))){
                PosUtil.analysis8583(res);
                //解析报文,返回解析的域map
                Map<String, String> map = Iso8583Parser.parser("pos", response, true);
                //需要获取2,4,11,12,13,14,37,38,39域信息
                String result2 = map.get("2");
                String result4 = map.get("4");
                String result11 = map.get("11");
                String result12 = map.get("12");
                String result13 = map.get("13");
                String result14 = map.get("14");
                String result37 = map.get("37");
                String result38 = map.get("38");
                String result39 = map.get("39");
                String result44 = map.get("61");
                String result62 = map.get("62");
                msg = "0_" + result2 + "_" +result4 + "_" +result11 + "_" + result12 + "_" +
                        result13 + "_" + result14 + "_" +result37 + "_" + result38 +"_"+result39 +
                        "_" +result44 + "_" + result62;
            }else{
                msg = "-1_";
            }
        }catch (Exception e) {
            e.printStackTrace();
            System.out.println("银生宝撤销响应报文解析错误");
        }
        System.out.println("结果为: " + msg);
    }
}
